module SingleCycle_CPU(
  input  clock,
  input  reset
);

wire RegDST, branch, memRead, mem2reg, memWrite, ALUsrc, regWrite, zero_flag, branch_zeroFlag;
wire [2:0]  ALUop, ALUctrl;
wire [4:0]  mux_RegDST;
wire [31:0] pc, PCplus4, PCoffset, Rs_Data, Rt_Data, mux_ALUsrc, mux_branch, mux_mem2reg, instr, immediate, offset, ALUresult, memData;


PC PC(
  .clock      (clock),
  .reset      (reset),
  .PC_in      (mux_branch),
  .PC_out     (pc)
);


Control Control(
  .oPCode     (instr[31:26]),
  .regDst     (RegDST),
  .branch     (branch),
  .memRead    (memRead),
  .mem2reg    (mem2reg),
  .ALUop      (ALUop),
  .memWrite   (memWrite),
  .ALUsrc     (ALUsrc),
  .regWrite   (regWrite)
);


ALU ALU(
  .data1_in   (Rs_Data),
  .data2_in   (mux_ALUsrc),
  .ALUctrl    (ALUctrl),
  .data       (ALUresult),
  .zero_flag  (zeroFlag)
);


ALU_Control ALU_Control(
  .funct      (instr[5:0]),
  .ALUop      (ALUop),
  .ALUctrl    (ALUctrl)
);


registerFile registerFile(
  .clock        (clock),
  .Rs_address   (instr[25:21]),
  .Rt_address   (instr[20:16]),
  .Rd_address   (mux_RegDST),
  .Rd_data      (mux_mem2reg),
  .regWrite     (regWrite),
  .Rs_data      (Rs_Data),
  .Rt_data      (Rt_Data)
);

adder pcplus4(
  .data1_in   (pc),
  .data2_in   (32'd4),
  .data_out   (PCplus4)
);


iMem iMem(
  .address    (pc),
  .instr      (instr)
);


dMem dMem(
  .clock      (clock),
  .address    (ALUresult),
  .data_in    (Rt_Data),
  .memRead    (memRead),
  .memWrite   (memWrite),
  .data_out   (memData)
);


signExtender signExtender(
  .data_in    (instr[15:0]),
  .data_out   (immediate)
);


adder PC_Add_offset(
  .data1_in   (PCplus4),
  .data2_in   (offset),
  .data_out   (PCoffset)
);


MUX_5bit MUX_regDst(
  .data1_in   (instr[20:16]),
  .data2_in   (instr[15:11]),
  .select     (RegDST),
  .data_out   (mux_RegDST)
);


MUX_32bit MUX_ALUsrc(
  .data1_in   (Rt_Data),
  .data2_in   (immediate),
  .select     (ALUsrc),
  .data_out   (mux_ALUsrc)
);


MUX_32bit MUX_branch(
  .data1_in   (PCplus4),
  .data2_in   (PCoffset),
  .select     (branch_zeroFlag),
  .data_out   (mux_branch)
);


MUX_32bit MUX_mem2reg(
  .data1_in   (ALUresult),
  .data2_in   (memData),
  .select     (mem2reg),
  .data_out   (mux_mem2reg)
);

assign offset = immediate << 2;
assign branch_zeroFlag = branch & zero_flag;
endmodule
